import sys
from pathlib import Path
from os.path import dirname, abspath
path = dirname(str(Path(__file__).resolve().parents[1]))
if path not in sys.path:
    sys.path.append(path)

class EsParam:
    def __init__(self, index):
        self.index = index
        self.term = []
        self.terms = []
        self.between = []
        self.ranges = []
        self.sources = []
        self.from_ = None
        self.size = None
        self.sorts = []
    
    def get_index(self):
        return self.index

    def set_from(self, from_: int):
        self.from_ = from_
        return self 
    
    def set_size(self, size: int):
        self.size = size
        return self

    def add_term(self, name: str, value: str, not_ = False):
        self.term.append({"term": {name: value, "not": not_}})
        return self
    
    def add_terms(self, name: str, values: list, not_ = False):
        self.terms.append({"terms": {name: values, "not": not_}})
        return self
    
    def range_gt(self, name: str, value: str):
        self.__add_range(name, value, "gt")
        return self
    
    def range_gte(self, name: str, value: str):
        self.__add_range(name, value, "gte")
        return self

    def range_lt(self, name: str, value: str):
        self.__add_range(name, value, "lt")
        return self
    
    def range_lte(self, name: str, value: str):
        self.__add_range(name, value, "lte")
        return self
    
    def add_source(self, name: str):
        self.sources.append(name)
        return self
    
    def set_sources(self, names: list):
        self.sources = names
        return self
    
    def add_sort(self, name: str, order: str = "asc"):
        self.sorts.append({name: {"order": order}})
        return self
    
    def __add_range(self, name: str, value: str, op: str):
        for ran in self.ranges:
            if "range" not in ran:
                ran["range"] = {}
            ranges = ran["range"]
            if name in ranges:
                ranges[name][op] = value
                return
            else:
                ranges[name] = {op: value}
                return
        self.ranges.append({"range": {name: {op: value}}})

    
    def get_body(self):
        body = {
            "query": {
                "bool": {}
            }
        }
        must_body = []
        must_not_body = []
        if len(self.term) > 0:
            for term in self.term:
                not_ = term["term"]["not"]
                term["term"].pop("not")
                if not_:
                    must_not_body.append(term)
                else:
                    must_body.append(term)
        if len(self.terms) > 0:
            for terms in self.terms:
                not_ = terms["terms"]["not"]
                terms["terms"].pop("not")
                if not_:
                    must_not_body.append(terms)
                else:
                    must_body.append(terms)
        if len(must_body) > 0:
            body["query"]["bool"]["must"] = must_body
        if len(must_not_body) > 0:
            body["query"]["bool"]["must_not"] = must_not_body

        ranges_body = []
        if len(self.ranges) > 0:
            for ran in self.ranges:
                ranges_body.append(ran)
        if len(ranges_body) > 0:
            if "must" not in body["query"]["bool"]:
                body["query"]["bool"]["must"] = ranges_body
            else:
                body["query"]["bool"]["must"].extend(ranges_body)

        if len(self.sources) > 0:
            body["_source"] = self.sources

        if len(self.sorts) > 0:
            body["sort"] = self.sorts

        if self.from_:
            body["from"] = self.from_
        if self.size is not None:
            body["size"] = self.size
        if len(body["query"]["bool"]) == 0:
            raise Exception("query is empty")
        return body
